package yueyong.salarymanagement.module.business.salary.service;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import yueyong.salarymanagement.common.exception.FileException;
import yueyong.salarymanagement.listener.ExcelReadListener;
import yueyong.salarymanagement.module.business.salary.domain.vo.FileProperties;
import yueyong.salarymanagement.module.business.salary.domain.vo.ItemData;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * Copyright: yueyong (c) 2022
 *
 * @author he.shaorong
 * @version 1.0
 * @date 2022/2/3
 */
@Service
public class SalaryFileService {

    private final Path fileStorageLocation; // 文件在本地存储的地址

    @Autowired
    public SalaryFileService(FileProperties fileProperties) {
        this.fileStorageLocation = Paths.get(fileProperties.getUploadDir()).toAbsolutePath().normalize();
        try {
            Files.createDirectories(this.fileStorageLocation);
        } catch (Exception ex) {
            throw new FileException("Could not create the directory where the uploaded files will be stored.", ex);
        }
    }

    /**
     * 存储文件到系统
     *
     * @param file 文件
     * @return 文件名
     */
    public String storeFile(MultipartFile file) {
        // Normalize file name


        String originalFileName = StringUtils.cleanPath(file.getOriginalFilename());

        String fileName = generateFileName(originalFileName);

        try {
            // Check if the file's name contains invalid characters
            if(fileName.contains("..")) {
                throw new FileException("Sorry! Filename contains invalid path sequence " + fileName);
            }

            // Copy file to the target location (Replacing existing file with the same name)
            Path targetLocation = this.fileStorageLocation.resolve(fileName);
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

            return fileName;
        } catch (IOException ex) {
            throw new FileException("Could not store file " + fileName + ". Please try again!", ex);
        }
    }

    public Pair<List<List<ItemData>>, Map<Integer, String>> readExcel(String fileName) {

        ExcelReadListener excelListener = new ExcelReadListener();

        String myFileName = this.fileStorageLocation + File.separator + fileName;

        EasyExcel.read(myFileName, excelListener).sheet().doRead();

        List<JSONObject> dataListOriginal = excelListener.dataList;

        List<String> dataList = dataListOriginal.stream()
                .map(data -> data.toString()).collect(Collectors.toList());
        System.out.println("dataList:" + dataList.toString());


        Map<Integer, String> headData = excelListener.importHeads;
        System.out.println("headData:" + headData.toString());

        List<List<ItemData>> itemDataListList = getItemDateList(dataListOriginal, headData);

        System.out.println("itemDataList:" + itemDataListList.toString());

        return Pair.of(itemDataListList, headData);

    }

    private static List<List<ItemData>> getItemDateList(List<JSONObject> dataListOriginal, Map<Integer, String> headData) {

        List<List<ItemData>> itemDataListList = new ArrayList<>();
        for(JSONObject jsonObject: dataListOriginal){
            List<ItemData> itemDataList = new ArrayList<>();
            for(Map.Entry<String, Object> entry: jsonObject.entrySet()) {
                itemDataList.add(new ItemData(Integer.valueOf(entry.getKey()), headData.get(Integer.valueOf(entry.getKey())), (String)entry.getValue()));
            }
            itemDataListList.add(itemDataList);
        }

        return itemDataListList;

    }

    private String generateFileName(String originalFileName) {
        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddhhmms"));
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        String fileType = originalFileName.substring(originalFileName.lastIndexOf("."));
        return time + uuid + fileType;
    }

    /**
     * 加载文件
     * @param fileName 文件名
     * @return 文件
     */
    public Resource loadFileAsResource(String fileName) {
        try {
            Path filePath = this.fileStorageLocation.resolve(fileName).normalize();
            Resource resource = new UrlResource(filePath.toUri());
            if(resource.exists()) {
                return resource;
            } else {
                throw new FileException("File not found " + fileName);
            }
        } catch (MalformedURLException ex) {
            throw new FileException("File not found " + fileName, ex);
        }
    }

}
